#include <semaphore.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <sys/sem.h>

/*
>abcd
abcd

>saasdsdsdafasfasf
saasdsdsdafasfasf

>dsads
dsads

>

 */

#define SEM_READ   0
#define SEM_WRITE  1

//调用semctl时 man文档要求定义这个数据类型
union semun {
   int val;
};               

//P操作
//semid : 信号灯集合id
//semindex: 第几个信号灯
void Poperation(int semid,int semindex){
   struct sembuf sbuf;
   sbuf.sem_num =  semindex;
   sbuf.sem_op = -1;
   //阻塞
   sbuf.sem_flg = 0;
   //1: 只操作一个信号灯
   semop(semid,&sbuf,1);
}

//V操作
//semid : 信号灯集合id
//semindex: 第几个信号灯
void Voperation(int semid,int semindex){
   struct sembuf sbuf;
   sbuf.sem_num =  semindex;
   sbuf.sem_op = 1;
   sbuf.sem_flg = 0;
   semop(semid,&sbuf,1);
}

int main(){
    key_t key;
    char *shmaddr;
    int semid,shmid;
	//创建key
    key = ftok(".",100);
    if(key<0){
        perror("ftok");
        return 0;
    }
    
	//创建两个信号灯
	//semid: 信号灯集id
    semid = semget(key,2,IPC_CREAT |0666);
    if(semid<0){
        perror("semget");
        return 0;
    }

	//创建共享内存，以及映射到用户空间
    shmid = shmget(key,500,IPC_CREAT |0666);
    shmaddr = shmat(shmid,NULL,0);

	//初始化信号灯集中的每个信号灯
    union semun mysem;
	//读信号灯  初始值是0
    mysem.val = 0;
    semctl(semid,SEM_READ,SETVAL,mysem);
	//写信号灯  初始值是1
    mysem.val = 1;
    semctl(semid,SEM_WRITE,SETVAL,mysem);

    pid_t pid;
    pid = fork();
    if(pid<0){
        perror("fork");
        shmctl(shmid,IPC_RMID,NULL);
        semctl(semid,0,IPC_RMID);
        exit(-1);
    }else if(pid == 0){
        while(1){
			//子进程  读
            Poperation(semid,SEM_READ);
            printf("%s\n",shmaddr);
            Voperation(semid,SEM_WRITE);
        }
    }else{
        while(1){
			//父进程 写
            Poperation(semid,SEM_WRITE);
            printf(">");
            fgets(shmaddr,32,stdin);
            Voperation(semid,SEM_READ);
        }
    }
}

